package com.shuwen.gcdj.service.dept;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.shuwen.gcdj.bean.dept.request.DepUpdateReq;
import com.shuwen.gcdj.bean.dept.response.DeptDetailResp;
import com.shuwen.gcdj.common.api.CommonPage;
import com.shuwen.gcdj.common.api.CommonResult;
import com.shuwen.gcdj.bean.AddResp;
import com.shuwen.gcdj.bean.dept.request.DeptAddReq;
import com.shuwen.gcdj.bean.dept.request.DeptListReq;
import com.shuwen.gcdj.bean.dept.response.DeptListItemResp;
import com.shuwen.gcdj.common.constant.Constants;
import com.shuwen.gcdj.common.enums.ErrorCode;
import com.shuwen.gcdj.common.error.ErrorReport;
import com.shuwen.gcdj.dto.account.InitUserDto;
import com.shuwen.gcdj.entity.Department;
import com.shuwen.gcdj.exception.IErrorCodeFactory;
import com.shuwen.gcdj.mapper.mysql.DepartmentMapper;
import com.shuwen.gcdj.service.BaseService;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.time.LocalDateTime;
import java.util.*;

@Service
@AllArgsConstructor
@Slf4j
public class DepartmentService extends BaseService<DepartmentMapper, Department> {

    private final DepartmentMapper departmentMapper;

    /**
     * 获取部门名称
     *
     * @param deptId      String
     * @param defaultName String
     * @return String
     */
    public String getDeptNameWithDefault(String deptId, String defaultName) {
        if (deptId == null || deptId.isEmpty()) {
            return defaultName;
        }

        Department department = getById(deptId);
        if (department == null || department.getName() == null) {
            return defaultName;
        }

        return department.getName();
    }

    /**
     * 获取当前部门ID + 所有子部门ID
     *
     * @param parentId List<String>
     * @return List<String>
     */
    public List<String> searchCurrentAndSubDeptIds(List<String> parentId) {
        List<DeptListItemResp> searches = searchCurrentAndSubDept(parentId);
        if (searches == null) {
            return new ArrayList<>();
        }

        List<String> resp = new ArrayList<>();
        for (DeptListItemResp item : searches) {
            resp.add(item.getId());
        }

        return resp;
    }

    /**
     * 获取当前部门 + 所有子部门
     *
     * @param parentId List<String>
     * @return List<Role>
     */
    public List<DeptListItemResp> searchCurrentAndSubDept(List<String> parentId) {
        List<Department> c;
        List<DeptListItemResp> resp = new ArrayList<>();
        if (parentId == null || parentId.isEmpty()) {
            return resp;
        }

        QueryWrapper<Department> qw = new QueryWrapper<>();
        qw.in("id", parentId);
        qw.eq(Constants.FIELD_KEY_IS_DELETE, Constants.IS_DELETE_NORMAL);
        c = departmentMapper.selectList(qw);
        if (c == null) {
            return new ArrayList<>();
        }

        searchSubDeptRec(parentId, c);
        for (Department department : c) {
            DeptListItemResp item = new DeptListItemResp();
            BeanUtils.copyProperties(department, item);
            resp.add(item);
        }

        log.info("-----------searchCurrentAndSubDept(parentId = {}) result: {}", parentId, resp);
        return resp;
    }

    /**
     * 获取所有子部门(不包含当前查询的部门)
     *
     * @param parentId List<String>
     * @return List<DeptListItemResp>
     */
    public List<DeptListItemResp> searchOnlySubDept(List<String> parentId) {
        List<Department> c = new ArrayList<>();
        List<DeptListItemResp> resp = new ArrayList<>();
        searchSubDeptRec(parentId, c);
        for (Department department : c) {
            DeptListItemResp item = new DeptListItemResp();
            BeanUtils.copyProperties(department, item);
            resp.add(item);
        }

        return resp;
    }


    /**
     * 递归调用获取子部门
     *
     * @param parentId List<String>
     */
    private void searchSubDeptRec(List<String> parentId, List<Department> c) {
        if (parentId == null || parentId.isEmpty()) {
            return;
        }

        QueryWrapper<Department> qw = new QueryWrapper<>();
        qw.in("parent_id", parentId);
        qw.eq(Constants.FIELD_KEY_IS_DELETE, Constants.IS_DELETE_NORMAL);
        List<Department> departments = departmentMapper.selectList(qw);
        if (departments != null) {
            List<String> newParentId = new ArrayList<>();
            for (Department department : departments) {
                newParentId.add(department.getId());
            }
            c.addAll(departments);
            searchSubDeptRec(newParentId, c);
        }
    }

    /**
     * 获取分页列表
     *
     * @param req DeptListReq
     * @return CommonResult<CommonPage < DeptListItemResp>>
     */
    public CommonResult<CommonPage<DeptListItemResp>> getPagingList(DeptListReq req) {
        Page<DeptListItemResp> page = new Page<>(req.getPageNum(), req.getPageSize(), true);
        IPage<DeptListItemResp> data = departmentMapper.getPagingList(page, req);
        List<DeptListItemResp> res = data.getRecords();
        Page<DeptListItemResp> resPage = new Page<>(page.getCurrent(), page.getSize(), page.getTotal());
        resPage.setRecords(res);
        return CommonResult.success(CommonPage.restPage(resPage));
    }

    /**
     * 获取所有部门
     *
     * @return CommonResult<List < DeptListItemResp>>
     */
    public CommonResult<List<DeptListItemResp>> getAllList() {
        List<DeptListItemResp> res = departmentMapper.getAllList();
        return CommonResult.success(res);
    }

    /**
     * 添加部门
     *
     * @param req         DeptAddReq
     * @param initUserDto InitUserDto
     * @return CommonResult<AddResp>
     */
    public CommonResult<AddResp> addDept(DeptAddReq req, InitUserDto initUserDto) {
        if (req == null) {
            return ErrorReport.fail(IErrorCodeFactory.create(ErrorCode.PARAM_INVALID.getCode(), "请求参数异常"));
        }

        if (req.getName() == null || req.getName().isEmpty()) {
            return ErrorReport.fail(IErrorCodeFactory.create(ErrorCode.PARAM_INVALID.getCode(), "部门名称不能为空"));
        }

        if (req.getParentId() == null) {
            req.setParentId("");
        }

        String name = req.getName();
        String pid = req.getParentId();

        // check
        LambdaQueryWrapper<Department> qr = new LambdaQueryWrapper<>();
        qr.eq(Department::getParentId, pid);
        qr.eq(Department::getName, name);
        qr.last("limit 1");
        Department one = getOne(qr);
        if (one != null) {
            log.error("DepartmentService.addDept(req = {}) error: 同一部门下已存在相同部门", req);
            return ErrorReport.fail(IErrorCodeFactory.create(ErrorCode.INVALID_OP.getCode(), String.format("同步们已存在相同部门名称[%s]", name)));
        }

        AddResp resp = new AddResp();
        if (!pid.isEmpty()) {
//            Department department = getById(pid);
//            if (department == null) {
//                log.error("DepartmentService.addDept(req = {}) error: 父级部门不存在", req);
//                return ErrorReport.fail(IErrorCodeFactory.create(ErrorCode.INVALID_OP.getCode(), String.format("父级部门[%s]不存在", pid)));
//            }
            Department addDept = new Department();
            addDept.setName(req.getName());
            addDept.setParentId(req.getParentId());
            addDept.setLevel(1);
            addDept.setNamePath("/");
            addDept.setIdPath("1");
            setCreatorUpdater(addDept, initUserDto);
            boolean insertResp = save(addDept);
            if (insertResp) {
                resp.setId(addDept.getId());
                // 更新idPath
                addDept.setIdPath(addDept.getIdPath() + "/" + addDept.getId());
                updateById(addDept);
                return CommonResult.success(resp);
            }

            log.error("DepartmentService.addDept(req = {}) save(addDept = {}) error : 添加失败", req, addDept);
            return ErrorReport.fail(IErrorCodeFactory.create(ErrorCode.INVALID_OP.getCode(), "添加部门失败"));
        }

        Department addDept = new Department();
        addDept.setName(req.getName());
        addDept.setParentId(req.getParentId());
        addDept.setLevel(1);
        addDept.setNamePath(req.getName());
        setCreatorUpdater(addDept, initUserDto);
        boolean insertResp = save(addDept);
        if (insertResp) {
            resp.setId(addDept.getId());
            // 更新idPath
            addDept.setIdPath(addDept.getId());
            updateById(addDept);
            return CommonResult.success(resp);
        }

        log.error("DepartmentService.addDept(req = {}) without parentId save(addDept = {}) error : 添加失败", req, addDept);
        return ErrorReport.fail(IErrorCodeFactory.create(ErrorCode.INVALID_OP.getCode(), "添加部门失败"));
    }

    /**
     * 修改部门
     *
     * @param req         DeptAddReq
     * @param initUserDto InitUserDto
     * @return CommonResult<AddResp>
     */
    public CommonResult<String> updateDept(DepUpdateReq req, InitUserDto initUserDto){
        Department department = departmentMapper.selectById(req.getId());
        BeanUtils.copyProperties(req,department);
        department.setUpdateId(initUserDto.getUserId());
        List<Department> departments = departmentMapper.selectList(new QueryWrapper<Department>().lambda()
                .eq(Department::getName, req.getName()));
        if (StringUtils.isEmpty(departments)) {
            return ErrorReport.fail(IErrorCodeFactory.create(ErrorCode.INVALID_OP.getCode(), String.format("同步们已存在相同部门名称[%s]", req.getName())));
        }
//        Department dep = getById(req.getParentId());
//        if (StringUtils.isEmpty(dep)) {
//            log.error("DepartmentService.addDept(req = {}) error: 父级部门不存在", req);
//            return ErrorReport.fail(IErrorCodeFactory.create(ErrorCode.INVALID_OP.getCode(), String.format("父级部门[%s]不存在", req.getParentId())));
//        }
        department.setLevel(1);
        department.setUpdateTime(LocalDateTime.now());
        departmentMapper.updateById(department);
        return CommonResult.success("修改成功");

    }

    /**
     * 删除部门
     *
     * @param depIds
     * @param initUserDto InitUserDto
     * @return CommonResult<AddResp>
     */
    public CommonResult<String> delete(String depIds, InitUserDto initUserDto){
        if (StringUtils.isEmpty(depIds)){
            return CommonResult.failed("部门id不能为空");
        }
        String [] id = depIds.split(",");
        for (String s : id) {
            int update = departmentMapper.update(null, new UpdateWrapper<Department>().lambda().eq(Department::getId, s)
                    .set(Department::getIsDelete,Constants.IS_DELETE_YES)
                    .set(Department::getUpdateId,initUserDto.getUserId()));
            if(update<1){
                return CommonResult.failed("删除的部门不存在或部门已被删除");
            }
        }
        return CommonResult.success("");
    }


    /**
     * 启用部门
     *
     * @param depId
     * @param initUserDto InitUserDto
     * @return CommonResult<AddResp>
     */
    public CommonResult<String> enable(String depId, InitUserDto initUserDto){
        if (StringUtils.isEmpty(depId)){
            return CommonResult.failed(ErrorCode.DATA_DEPTID_EXIST);
        }
      departmentMapper.update(null, new UpdateWrapper<Department>().lambda()
                .eq(Department::getId, depId)
                .set(Department::getIsDelete, Constants.IS_DELETE_NORMAL)
                .set(Department::getUpdateId, initUserDto.getUserId()));
        return CommonResult.success("");
    }

    /**
     * 部门详情
     *
     * @param depId
     * @return CommonResult<AddResp>
     */
    public CommonResult<DeptDetailResp> depDetail(String depId){
        if (StringUtils.isEmpty(depId)){
            return CommonResult.failed("部门id不能为空");
        }
        Department department = departmentMapper.selectById(depId);
        DeptDetailResp deptDetailResp =new DeptDetailResp();
        BeanUtils.copyProperties(department,deptDetailResp);
        return CommonResult.success(deptDetailResp);
    }
    private void setCreatorUpdater(Department department, InitUserDto initUserDto) {
        if (initUserDto != null) {
            Optional.ofNullable(initUserDto.getUserId()).ifPresent(department::setCreateId);
            Optional.ofNullable(initUserDto.getUserId()).ifPresent(department::setUpdateId);
        }
    }
}
